<template>
  <div class="rule-engine-container">
    <!-- 页面头部 -->
    <div class="page-header">
      <div class="header-left">
        <h1 class="page-title">规则引擎管理</h1>
        <p class="page-subtitle">可视化编辑、管理、部署用于报警、任务匹配、简单诊断的规则流</p>
      </div>
      <div class="header-right">
        <button class="header-btn" @click="showTemplates">
          📋 流程模板
        </button>
        <button class="header-btn" @click="exportFlow">
          📤 导出配置
        </button>
        <button class="header-btn" @click="importFlow">
          📥 导入配置
        </button>
        <button class="header-btn primary" @click="deployFlow">
          🚀 部署流程
        </button>
      </div>
    </div>

    <!-- 工具栏 -->
    <div class="toolbar">
      <div class="tool-section">
        <h4>连接状态</h4>
        <div class="connection-status" :class="connectionStatus">
          <span class="status-dot"></span>
          <span class="status-text">{{ getConnectionStatusText() }}</span>
          <button 
            v-if="connectionStatus !== 'connected'"
            class="reconnect-btn"
            @click="reconnectNodeRed"
          >
            重新连接
          </button>
        </div>
      </div>

      <div class="tool-section">
        <h4>快速操作</h4>
        <div class="quick-actions">
          <button class="tool-btn" @click="createNewFlow">
            ➕ 新建流程
          </button>
          <button class="tool-btn" @click="saveFlow">
            💾 保存流程
          </button>
          <button class="tool-btn" @click="validateFlow">
            ✅ 验证流程
          </button>
          <button class="tool-btn" @click="clearFlow">
            🗑️ 清空画布
          </button>
        </div>
      </div>

      <div class="tool-section">
        <h4>流程库</h4>
        <div class="flow-library">
          <select v-model="selectedFlow" class="flow-select" @change="loadSelectedFlow">
            <option value="">选择已保存的流程</option>
            <option v-for="flow in savedFlows" :key="flow.id" :value="flow.id">
              {{ flow.name }} ({{ flow.type }})
            </option>
          </select>
          <button 
            class="load-btn"
            @click="loadSelectedFlow"
            :disabled="!selectedFlow"
          >
            加载
          </button>
        </div>
      </div>
    </div>

    <!-- 主要编辑区域 -->
    <div class="main-editor">
      <!-- 左侧节点面板 -->
      <div class="node-palette">
        <h3 class="palette-title">节点库</h3>
        
        <div class="node-category">
          <h4 class="category-title">输入节点</h4>
          <div class="node-list">
            <div 
              v-for="node in inputNodes" 
              :key="node.type"
              class="node-item"
              :title="node.description"
              draggable="true"
              @dragstart="onNodeDragStart($event, node)"
            >
              <span class="node-icon">{{ node.icon }}</span>
              <span class="node-name">{{ node.name }}</span>
            </div>
          </div>
        </div>

        <div class="node-category">
          <h4 class="category-title">处理节点</h4>
          <div class="node-list">
            <div 
              v-for="node in processNodes" 
              :key="node.type"
              class="node-item"
              :title="node.description"
              draggable="true"
              @dragstart="onNodeDragStart($event, node)"
            >
              <span class="node-icon">{{ node.icon }}</span>
              <span class="node-name">{{ node.name }}</span>
            </div>
          </div>
        </div>

        <div class="node-category">
          <h4 class="category-title">输出节点</h4>
          <div class="node-list">
            <div 
              v-for="node in outputNodes" 
              :key="node.type"
              class="node-item"
              :title="node.description"
              draggable="true"
              @dragstart="onNodeDragStart($event, node)"
            >
              <span class="node-icon">{{ node.icon }}</span>
              <span class="node-name">{{ node.name }}</span>
            </div>
          </div>
        </div>

        <div class="node-category">
          <h4 class="category-title">特殊节点</h4>
          <div class="node-list">
            <div 
              v-for="node in specialNodes" 
              :key="node.type"
              class="node-item"
              :title="node.description"
              draggable="true"
              @dragstart="onNodeDragStart($event, node)"
            >
              <span class="node-icon">{{ node.icon }}</span>
              <span class="node-name">{{ node.name }}</span>
            </div>
          </div>
        </div>
      </div>

      <!-- Node-RED编辑器 -->
      <div class="editor-container">
        <div class="editor-header">
          <div class="editor-tabs">
            <div 
              v-for="tab in editorTabs" 
              :key="tab.id"
              class="editor-tab"
              :class="{ active: activeTab === tab.id }"
              @click="switchTab(tab.id)"
            >
              <span class="tab-icon">{{ tab.icon }}</span>
              <span class="tab-name">{{ tab.name }}</span>
              <button 
                v-if="tab.closable"
                class="tab-close"
                @click.stop="closeTab(tab.id)"
              >
                ×
              </button>
            </div>
            <button class="add-tab-btn" @click="addNewTab">+</button>
          </div>
          
          <div class="editor-info">
            <span class="flow-status">
              状态: <span :class="flowStatus.toLowerCase()">{{ flowStatus }}</span>
            </span>
            <span class="node-count">节点数: {{ nodeCount }}</span>
          </div>
        </div>

        <!-- Node-RED iframe -->
        <iframe
          ref="nodeRedFrame"
          class="node-red-iframe"
          :src="nodeRedUrl"
          @load="onNodeRedLoad"
          frameborder="0"
        ></iframe>

        <!-- 编辑器工具栏 -->
        <div class="editor-toolbar">
          <div class="toolbar-left">
            <button class="toolbar-btn" @click="zoomIn">🔍+</button>
            <button class="toolbar-btn" @click="zoomOut">🔍-</button>
            <button class="toolbar-btn" @click="resetZoom">🔄</button>
            <span class="zoom-level">{{ zoomLevel }}%</span>
          </div>
          
          <div class="toolbar-center">
            <button class="toolbar-btn" @click="undoAction">↶ 撤销</button>
            <button class="toolbar-btn" @click="redoAction">↷ 重做</button>
            <button class="toolbar-btn" @click="selectAll">全选</button>
            <button class="toolbar-btn" @click="deleteSelected">删除</button>
          </div>
          
          <div class="toolbar-right">
            <button class="toolbar-btn" @click="toggleGrid">📐 网格</button>
            <button class="toolbar-btn" @click="autoLayout">🎯 自动布局</button>
            <button class="toolbar-btn" @click="fullscreen">⛶ 全屏</button>
          </div>
        </div>
      </div>

      <!-- 右侧属性面板 -->
      <div class="properties-panel">
        <h3 class="panel-title">属性面板</h3>
        
        <div v-if="selectedNode" class="node-properties">
          <div class="property-section">
            <h4>基本属性</h4>
            <div class="property-item">
              <label class="property-label">节点名称</label>
              <input 
                v-model="selectedNode.name" 
                type="text" 
                class="property-input"
                @change="updateNodeProperty('name', selectedNode.name)"
              />
            </div>
            <div class="property-item">
              <label class="property-label">节点类型</label>
              <span class="property-value">{{ selectedNode.type }}</span>
            </div>
            <div class="property-item">
              <label class="property-label">节点ID</label>
              <span class="property-value">{{ selectedNode.id }}</span>
            </div>
          </div>

          <div class="property-section">
            <h4>配置属性</h4>
            <div 
              v-for="(value, key) in selectedNode.config" 
              :key="key"
              class="property-item"
            >
              <label class="property-label">{{ getPropertyLabel(key) }}</label>
              <input 
                v-if="getPropertyType(key) === 'text'"
                v-model="selectedNode.config[key]"
                type="text" 
                class="property-input"
                @change="updateNodeProperty('config.' + key, selectedNode.config[key])"
              />
              <input 
                v-else-if="getPropertyType(key) === 'number'"
                v-model.number="selectedNode.config[key]"
                type="number" 
                class="property-input"
                @change="updateNodeProperty('config.' + key, selectedNode.config[key])"
              />
              <select 
                v-else-if="getPropertyType(key) === 'select'"
                v-model="selectedNode.config[key]"
                class="property-select"
                @change="updateNodeProperty('config.' + key, selectedNode.config[key])"
              >
                <option v-for="option in getPropertyOptions(key)" :key="option.value" :value="option.value">
                  {{ option.label }}
                </option>
              </select>
              <textarea 
                v-else
                v-model="selectedNode.config[key]"
                class="property-textarea"
                @change="updateNodeProperty('config.' + key, selectedNode.config[key])"
                rows="3"
              ></textarea>
            </div>
          </div>

          <div class="property-section">
            <h4>输入/输出</h4>
            <div class="io-config">
              <div class="io-item">
                <span class="io-label">输入端口数</span>
                <span class="io-value">{{ selectedNode.inputs || 0 }}</span>
              </div>
              <div class="io-item">
                <span class="io-label">输出端口数</span>
                <span class="io-value">{{ selectedNode.outputs || 0 }}</span>
              </div>
            </div>
          </div>
        </div>

        <div v-else class="no-selection">
          <div class="no-selection-icon">📝</div>
          <p>请选择一个节点查看属性</p>
        </div>

        <!-- 流程信息 -->
        <div class="flow-info">
          <h4>流程信息</h4>
          <div class="info-item">
            <span class="info-label">流程名称</span>
            <input 
              v-model="currentFlow.name" 
              type="text" 
              class="info-input"
              placeholder="输入流程名称"
            />
          </div>
          <div class="info-item">
            <span class="info-label">流程类型</span>
            <select v-model="currentFlow.type" class="info-select">
              <option value="alarm">报警规则</option>
              <option value="task">任务匹配</option>
              <option value="diagnosis">简单诊断</option>
              <option value="workflow">工作流程</option>
            </select>
          </div>
          <div class="info-item">
            <span class="info-label">描述</span>
            <textarea 
              v-model="currentFlow.description" 
              class="info-textarea"
              placeholder="描述流程的用途和功能"
              rows="3"
            ></textarea>
          </div>
        </div>
      </div>
    </div>

    <!-- 底部状态栏 -->
    <div class="status-bar">
      <div class="status-left">
        <span class="status-item">
          <span class="status-icon">🔗</span>
          连接: {{ connectionStatus === 'connected' ? 'Node-RED' : '离线' }}
        </span>
        <span class="status-item">
          <span class="status-icon">📊</span>
          流程: {{ currentFlow.name || '未命名' }}
        </span>
        <span class="status-item">
          <span class="status-icon">🔧</span>
          节点: {{ nodeCount }}
        </span>
      </div>
      
      <div class="status-right">
        <span class="status-item">
          <span class="status-icon">💾</span>
          {{ lastSaved ? '已保存 ' + formatTime(lastSaved) : '未保存' }}
        </span>
        <span class="status-item">
          <span class="status-icon">🚀</span>
          {{ isDeployed ? '已部署' : '未部署' }}
        </span>
      </div>
    </div>

    <!-- 模板库弹窗 -->
    <div v-if="showTemplateDialog" class="modal-overlay" @click="closeTemplateDialog">
      <div class="modal-content" @click.stop>
        <div class="modal-header">
          <h3>流程模板库</h3>
          <button class="close-btn" @click="closeTemplateDialog">×</button>
        </div>
        
        <div class="modal-body">
          <div class="template-grid">
            <div 
              v-for="template in flowTemplates" 
              :key="template.id"
              class="template-card"
              @click="loadTemplate(template)"
            >
              <div class="template-icon">{{ template.icon }}</div>
              <div class="template-info">
                <h4 class="template-name">{{ template.name }}</h4>
                <p class="template-description">{{ template.description }}</p>
                <div class="template-meta">
                  <span class="template-type">{{ template.type }}</span>
                  <span class="template-nodes">{{ template.nodeCount }} 节点</span>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, reactive, computed } from 'vue'

// 响应式数据
const nodeRedFrame = ref(null)
const nodeRedUrl = ref('http://localhost:1880') // Node-RED实例URL
const connectionStatus = ref('disconnected') // connected, connecting, disconnected
const selectedFlow = ref('')
const activeTab = ref('main')
const zoomLevel = ref(100)
const nodeCount = ref(0)
const flowStatus = ref('停止')
const lastSaved = ref(null)
const isDeployed = ref(false)

const showTemplateDialog = ref(false)

// 当前选中的节点
const selectedNode = ref(null)

// 当前流程信息
const currentFlow = reactive({
  name: '',
  type: 'alarm',
  description: ''
})

// 编辑器标签页
const editorTabs = ref([
  { id: 'main', name: '主流程', icon: '🏠', closable: false }
])

// 已保存的流程
const savedFlows = ref([
  { id: 'flow1', name: '发动机温度报警', type: '报警规则' },
  { id: 'flow2', name: '维护任务匹配', type: '任务匹配' },
  { id: 'flow3', name: '传感器故障诊断', type: '简单诊断' },
  { id: 'flow4', name: '武器系统检查', type: '工作流程' }
])

// 节点库定义
const inputNodes = ref([
  { type: 'sensor-input', name: '传感器输入', icon: '📡', description: '接收传感器数据' },
  { type: 'mqtt-input', name: 'MQTT输入', icon: '📨', description: '接收MQTT消息' },
  { type: 'http-input', name: 'HTTP输入', icon: '🌐', description: '接收HTTP请求' },
  { type: 'timer-input', name: '定时器', icon: '⏰', description: '定时触发' },
  { type: 'file-input', name: '文件输入', icon: '📁', description: '读取文件数据' }
])

const processNodes = ref([
  { type: 'filter', name: '数据过滤', icon: '🔍', description: '过滤和筛选数据' },
  { type: 'transform', name: '数据转换', icon: '🔄', description: '转换数据格式' },
  { type: 'logic', name: '逻辑判断', icon: '🧠', description: '条件逻辑处理' },
  { type: 'calculation', name: '计算处理', icon: '🧮', description: '数值计算' },
  { type: 'aggregation', name: '数据聚合', icon: '📊', description: '聚合统计数据' },
  { type: 'threshold', name: '阈值检测', icon: '⚠️', description: '阈值比较' },
  { type: 'pattern', name: '模式匹配', icon: '🎯', description: '模式识别' }
])

const outputNodes = ref([
  { type: 'alarm-output', name: '报警输出', icon: '🚨', description: '发送报警信息' },
  { type: 'email-output', name: '邮件发送', icon: '📧', description: '发送邮件通知' },
  { type: 'sms-output', name: '短信发送', icon: '📱', description: '发送短信通知' },
  { type: 'database-output', name: '数据库存储', icon: '💾', description: '存储到数据库' },
  { type: 'log-output', name: '日志记录', icon: '📝', description: '记录日志' },
  { type: 'api-output', name: 'API调用', icon: '🔗', description: '调用外部API' }
])

const specialNodes = ref([
  { type: 'delay', name: '延迟节点', icon: '⏱️', description: '延迟处理' },
  { type: 'switch', name: '分支节点', icon: '🔀', description: '条件分支' },
  { type: 'join', name: '合并节点', icon: '🔗', description: '合并多个输入' },
  { type: 'split', name: '分割节点', icon: '✂️', description: '分割数据' },
  { type: 'cache', name: '缓存节点', icon: '💿', description: '缓存数据' },
  { type: 'rate-limit', name: '限流节点', icon: '🚦', description: '流量控制' }
])

// 流程模板
const flowTemplates = ref([
  {
    id: 'template1',
    name: '发动机温度监控',
    type: '报警规则',
    icon: '🌡️',
    description: '监控发动机温度，超过阈值时发送报警',
    nodeCount: 5
  },
  {
    id: 'template2',
    name: '设备状态诊断',
    type: '简单诊断',
    icon: '🔧',
    description: '基于传感器数据诊断设备运行状态',
    nodeCount: 8
  },
  {
    id: 'template3',
    name: '维护任务调度',
    type: '任务匹配',
    icon: '📅',
    description: '根据设备状态自动匹配维护任务',
    nodeCount: 6
  },
  {
    id: 'template4',
    name: '数据采集流程',
    type: '工作流程',
    icon: '📊',
    description: '标准的传感器数据采集和处理流程',
    nodeCount: 10
  }
])

// 计算属性
const getConnectionStatusText = () => {
  const statusMap = {
    connected: '已连接',
    connecting: '连接中',
    disconnected: '未连接'
  }
  return statusMap[connectionStatus.value] || '未知'
}

// 方法
const onNodeRedLoad = () => {
  console.log('Node-RED编辑器已加载')
  connectionStatus.value = 'connected'
  
  // 模拟与Node-RED的通信
  simulateNodeRedCommunication()
}

const simulateNodeRedCommunication = () => {
  // 模拟节点数量变化
  setInterval(() => {
    nodeCount.value = Math.floor(Math.random() * 20) + 5
  }, 3000)
  
  // 模拟流程状态变化
  setTimeout(() => {
    flowStatus.value = '运行中'
  }, 2000)
}

const reconnectNodeRed = () => {
  connectionStatus.value = 'connecting'
  console.log('重新连接Node-RED...')
  
  setTimeout(() => {
    connectionStatus.value = Math.random() > 0.3 ? 'connected' : 'disconnected'
  }, 2000)
}

const createNewFlow = () => {
  console.log('创建新流程')
  currentFlow.name = ''
  currentFlow.type = 'alarm'
  currentFlow.description = ''
  nodeCount.value = 0
  selectedNode.value = null
}

const saveFlow = () => {
  console.log('保存流程')
  lastSaved.value = new Date()
  
  // 模拟保存到服务器
  const newFlow = {
    id: 'flow' + Date.now(),
    name: currentFlow.name || '未命名流程',
    type: getFlowTypeText(currentFlow.type)
  }
  
  savedFlows.value.push(newFlow)
}

const validateFlow = () => {
  console.log('验证流程')
  // 模拟验证结果
  setTimeout(() => {
    alert('流程验证通过！')
  }, 1000)
}

const clearFlow = () => {
  if (confirm('确定要清空当前画布吗？')) {
    console.log('清空画布')
    nodeCount.value = 0
    selectedNode.value = null
  }
}

const loadSelectedFlow = () => {
  if (!selectedFlow.value) return
  
  const flow = savedFlows.value.find(f => f.id === selectedFlow.value)
  if (flow) {
    console.log('加载流程:', flow.name)
    currentFlow.name = flow.name
    // 模拟加载节点
    nodeCount.value = Math.floor(Math.random() * 15) + 3
  }
}

const deployFlow = () => {
  console.log('部署流程')
  isDeployed.value = true
  flowStatus.value = '运行中'
  
  setTimeout(() => {
    alert('流程部署成功！')
  }, 1000)
}

const exportFlow = () => {
  console.log('导出配置')
  // 模拟导出
  const config = {
    name: currentFlow.name,
    type: currentFlow.type,
    nodes: nodeCount.value,
    timestamp: new Date().toISOString()
  }
  
  const blob = new Blob([JSON.stringify(config, null, 2)], { type: 'application/json' })
  const url = URL.createObjectURL(blob)
  const a = document.createElement('a')
  a.href = url
  a.download = `flow-${currentFlow.name || 'unnamed'}.json`
  a.click()
  URL.revokeObjectURL(url)
}

const importFlow = () => {
  console.log('导入配置')
  const input = document.createElement('input')
  input.type = 'file'
  input.accept = '.json'
  input.onchange = (e) => {
    const file = e.target.files[0]
    if (file) {
      const reader = new FileReader()
      reader.onload = (e) => {
        try {
          const config = JSON.parse(e.target.result)
          currentFlow.name = config.name || ''
          currentFlow.type = config.type || 'alarm'
          nodeCount.value = config.nodes || 0
          alert('配置导入成功！')
        } catch (error) {
          alert('配置文件格式错误！')
        }
      }
      reader.readAsText(file)
    }
  }
  input.click()
}

const showTemplates = () => {
  showTemplateDialog.value = true
}

const closeTemplateDialog = () => {
  showTemplateDialog.value = false
}

const loadTemplate = (template) => {
  console.log('加载模板:', template.name)
  currentFlow.name = template.name
  currentFlow.type = template.type === '报警规则' ? 'alarm' : template.type === '任务匹配' ? 'task' : template.type === '简单诊断' ? 'diagnosis' : 'workflow'
  currentFlow.description = template.description
  nodeCount.value = template.nodeCount
  
  closeTemplateDialog()
}

const onNodeDragStart = (event, node) => {
  event.dataTransfer.setData('text/plain', JSON.stringify(node))
  console.log('拖拽节点:', node.name)
}

const switchTab = (tabId) => {
  activeTab.value = tabId
}

const closeTab = (tabId) => {
  if (tabId === 'main') return // 主流程不能关闭
  
  const index = editorTabs.value.findIndex(tab => tab.id === tabId)
  if (index > -1) {
    editorTabs.value.splice(index, 1)
    if (activeTab.value === tabId) {
      activeTab.value = editorTabs.value[0].id
    }
  }
}

const addNewTab = () => {
  const newTab = {
    id: 'tab' + Date.now(),
    name: '子流程' + (editorTabs.value.length),
    icon: '📄',
    closable: true
  }
  editorTabs.value.push(newTab)
  activeTab.value = newTab.id
}

const zoomIn = () => {
  if (zoomLevel.value < 200) {
    zoomLevel.value += 10
    console.log('放大到:', zoomLevel.value + '%')
  }
}

const zoomOut = () => {
  if (zoomLevel.value > 50) {
    zoomLevel.value -= 10
    console.log('缩小到:', zoomLevel.value + '%')
  }
}

const resetZoom = () => {
  zoomLevel.value = 100
  console.log('重置缩放')
}

const undoAction = () => {
  console.log('撤销操作')
}

const redoAction = () => {
  console.log('重做操作')
}

const selectAll = () => {
  console.log('全选节点')
}

const deleteSelected = () => {
  console.log('删除选中节点')
  if (nodeCount.value > 0) {
    nodeCount.value--
  }
}

const toggleGrid = () => {
  console.log('切换网格显示')
}

const autoLayout = () => {
  console.log('自动布局')
}

const fullscreen = () => {
  console.log('切换全屏')
}

const updateNodeProperty = (path, value) => {
  console.log('更新节点属性:', path, value)
  // 在实际应用中，这里会与Node-RED通信更新节点属性
}

const getPropertyLabel = (key) => {
  const labelMap = {
    threshold: '阈值',
    interval: '间隔时间',
    topic: '主题',
    payload: '负载',
    method: '方法',
    url: 'URL地址',
    timeout: '超时时间'
  }
  return labelMap[key] || key
}

const getPropertyType = (key) => {
  const typeMap = {
    threshold: 'number',
    interval: 'number',
    timeout: 'number',
    method: 'select',
    topic: 'text',
    url: 'text',
    payload: 'textarea'
  }
  return typeMap[key] || 'text'
}

const getPropertyOptions = (key) => {
  const optionsMap = {
    method: [
      { value: 'GET', label: 'GET' },
      { value: 'POST', label: 'POST' },
      { value: 'PUT', label: 'PUT' },
      { value: 'DELETE', label: 'DELETE' }
    ]
  }
  return optionsMap[key] || []
}

const getFlowTypeText = (type) => {
  const typeMap = {
    alarm: '报警规则',
    task: '任务匹配',
    diagnosis: '简单诊断',
    workflow: '工作流程'
  }
  return typeMap[type] || type
}

const formatTime = (timestamp) => {
  return timestamp.toLocaleTimeString('zh-CN')
}

onMounted(() => {
  console.log('规则引擎管理页面已加载')
  
  // 模拟选中一个节点
  setTimeout(() => {
    selectedNode.value = {
      id: 'node1',
      name: '温度传感器',
      type: 'sensor-input',
      inputs: 0,
      outputs: 1,
      config: {
        threshold: 75,
        interval: 5000,
        topic: 'sensor/temperature'
      }
    }
  }, 2000)
})
</script>

<style scoped>
.rule-engine-container {
  width: 96vw;
  height: 100vh;
  color: #fff;
  display: flex;
  flex-direction: column;
}

.page-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 1vh 2vw;
  background: rgba(255,255,255,0.1);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid rgba(255,255,255,0.2);
}

.page-title {
  font-size: 2.8vw;
  margin: 0 0 0.3vh 0;
  font-weight: 700;
  text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
}

.page-subtitle {
  font-size: 1.3vw;
  margin: 0;
  opacity: 0.9;
}

.header-right {
  display: flex;
  gap: 1vw;
}

.header-btn {
  background: rgba(255,255,255,0.1);
  border: 1px solid rgba(255,255,255,0.2);
  color: #fff;
  padding: 0.8vh 1.5vw;
  border-radius: 6px;
  cursor: pointer;
  font-size: 1vw;
  font-weight: 500;
  transition: all 0.3s ease;
  backdrop-filter: blur(10px);
}

.header-btn:hover {
  background: rgba(255,255,255,0.2);
  transform: translateY(-1px);
}

.header-btn.primary {
  background: linear-gradient(45deg, #4CAF50, #45a049);
  border-color: #4CAF50;
}

.toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 1vh 2vw;
  background: rgba(255,255,255,0.05);
  border-bottom: 1px solid rgba(255,255,255,0.1);
  flex-wrap: wrap;
  gap: 2vw;
}

.tool-section {
  display: flex;
  flex-direction: column;
  gap: 0.5vh;
}

.tool-section h4 {
  margin: 0;
  font-size: 1.1vw;
  opacity: 0.8;
}

.connection-status {
  display: flex;
  align-items: center;
  gap: 0.8vw;
  font-size: 1vw;
}

.status-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #9E9E9E;
}

.connection-status.connected .status-dot {
  background: #4CAF50;
}

.connection-status.connecting .status-dot {
  background: #FF9800;
  animation: pulse 1s infinite;
}

.reconnect-btn {
  background: rgba(255,255,255,0.1);
  border: 1px solid rgba(255,255,255,0.3);
  color: #fff;
  padding: 0.3vh 0.8vw;
  border-radius: 4px;
  cursor: pointer;
  font-size: 0.9vw;
}

.quick-actions {
  display: flex;
  gap: 0.8vw;
}

.tool-btn {
  background: rgba(255,255,255,0.1);
  border: 1px solid rgba(255,255,255,0.3);
  color: #fff;
  padding: 0.5vh 1vw;
  border-radius: 5px;
  cursor: pointer;
  font-size: 0.9vw;
  transition: background 0.3s ease;
}

.tool-btn:hover {
  background: rgba(255,255,255,0.2);
}

.flow-library {
  display: flex;
  gap: 0.8vw;
  align-items: center;
}

.flow-select {
  background: rgba(255,255,255,0.1);
  border: 1px solid rgba(255,255,255,0.3);
  color: #fff;
  padding: 0.6vh 1vw;
  border-radius: 5px;
  font-size: 0.9vw;
  min-width: 200px;
}

.flow-select option {
  background: #333;
  color: #fff;
}

.load-btn {
  background: rgba(76, 175, 80, 0.2);
  border: 1px solid #4CAF50;
  color: #fff;
  padding: 0.6vh 1.2vw;
  border-radius: 5px;
  cursor: pointer;
  font-size: 0.9vw;
}

.load-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.main-editor {
  flex: 1;
  display: flex;
  height: calc(100vh - 16vh);
}

.node-palette {
  width: 20vw;
  background: rgba(255,255,255,0.1);
  border-right: 1px solid rgba(255,255,255,0.2);
  padding: 1vh 1vw;
  overflow-y: auto;
  backdrop-filter: blur(10px);
}

.palette-title {
  font-size: 1.4vw;
  margin: 0 0 1.5vh 0;
  text-align: center;
  color: #4CAF50;
}

.node-category {
  margin-bottom: 2vh;
}

.category-title {
  font-size: 1.2vw;
  margin: 0 0 1vh 0;
  padding-bottom: 0.5vh;
  border-bottom: 1px solid rgba(255,255,255,0.2);
  color: rgba(255,255,255,0.9);
}

.node-list {
  display: flex;
  flex-direction: column;
  gap: 0.5vh;
}

.node-item {
  display: flex;
  align-items: center;
  gap: 0.8vw;
  padding: 0.8vh 1vw;
  background: rgba(255,255,255,0.05);
  border-radius: 6px;
  cursor: grab;
  transition: all 0.3s ease;
  border: 1px solid transparent;
}

.node-item:hover {
  background: rgba(255,255,255,0.1);
  transform: translateX(3px);
  border-color: rgba(255,255,255,0.3);
}

.node-item:active {
  cursor: grabbing;
}

.node-icon {
  font-size: 1.2vw;
}

.node-name {
  font-size: 1vw;
  flex: 1;
}

.editor-container {
  flex: 1;
  display: flex;
  flex-direction: column;
  background: rgba(255,255,255,0.05);
}

.editor-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.8vh 1.5vw;
  background: rgba(255,255,255,0.1);
  border-bottom: 1px solid rgba(255,255,255,0.2);
}

.editor-tabs {
  display: flex;
  gap: 0.5vw;
  align-items: center;
}

.editor-tab {
  display: flex;
  align-items: center;
  gap: 0.5vw;
  padding: 0.6vh 1.2vw;
  background: rgba(255,255,255,0.1);
  border-radius: 6px 6px 0 0;
  cursor: pointer;
  font-size: 0.9vw;
  transition: background 0.3s ease;
}

.editor-tab.active {
  background: rgba(255,255,255,0.2);
  border-bottom: 2px solid #4CAF50;
}

.tab-close {
  background: none;
  border: none;
  color: #fff;
  cursor: pointer;
  font-size: 1.2vw;
  padding: 0;
  margin-left: 0.5vw;
}

.add-tab-btn {
  background: rgba(255,255,255,0.1);
  border: 1px solid rgba(255,255,255,0.3);
  color: #fff;
  cursor: pointer;
  font-size: 1.2vw;
  padding: 0.5vh 0.8vw;
  border-radius: 4px;
}

.editor-info {
  display: flex;
  gap: 2vw;
  font-size: 0.9vw;
}

.flow-status span {
  font-weight: 600;
}

.flow-status .停止 {
  color: #9E9E9E;
}

.flow-status .运行中 {
  color: #4CAF50;
}

.node-red-iframe {
  flex: 1;
  width: 100%;
  background: #fff;
  border: none;
}

.editor-toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.8vh 1.5vw;
  background: rgba(255,255,255,0.1);
  border-top: 1px solid rgba(255,255,255,0.2);
  flex-wrap: wrap;
  gap: 1vw;
}

.toolbar-left, .toolbar-center, .toolbar-right {
  display: flex;
  gap: 0.8vw;
  align-items: center;
}

.toolbar-btn {
  background: rgba(255,255,255,0.1);
  border: 1px solid rgba(255,255,255,0.3);
  color: #fff;
  padding: 0.5vh 1vw;
  border-radius: 4px;
  cursor: pointer;
  font-size: 0.9vw;
  transition: background 0.3s ease;
}

.toolbar-btn:hover {
  background: rgba(255,255,255,0.2);
}

.zoom-level {
  font-size: 0.9vw;
  color: rgba(255,255,255,0.8);
  min-width: 50px;
  text-align: center;
}

.properties-panel {
  width: 25vw;
  background: rgba(255,255,255,0.1);
  border-left: 1px solid rgba(255,255,255,0.2);
  padding: 1vh 1vw;
  overflow-y: auto;
  backdrop-filter: blur(10px);
}

.panel-title {
  font-size: 1.4vw;
  margin: 0 0 1.5vh 0;
  text-align: center;
  color: #4CAF50;
}

.node-properties {
  margin-bottom: 3vh;
}

.property-section {
  margin-bottom: 2vh;
  background: rgba(255,255,255,0.05);
  border-radius: 8px;
  padding: 1.5vh 1vw;
}

.property-section h4 {
  margin: 0 0 1vh 0;
  font-size: 1.2vw;
  color: #4CAF50;
  border-bottom: 1px solid rgba(255,255,255,0.2);
  padding-bottom: 0.5vh;
}

.property-item {
  margin-bottom: 1vh;
  display: flex;
  flex-direction: column;
  gap: 0.5vh;
}

.property-label {
  font-size: 1vw;
  opacity: 0.8;
}

.property-value {
  font-size: 1vw;
  font-weight: 600;
  color: rgba(255,255,255,0.9);
}

.property-input, .property-select, .property-textarea {
  background: rgba(255,255,255,0.1);
  border: 1px solid rgba(255,255,255,0.3);
  border-radius: 5px;
  color: #fff;
  padding: 0.6vh 0.8vw;
  font-size: 0.9vw;
  outline: none;
}

.property-input:focus, .property-select:focus, .property-textarea:focus {
  border-color: #4CAF50;
  box-shadow: 0 0 5px rgba(76, 175, 80, 0.3);
}

.property-textarea {
  resize: vertical;
  min-height: 60px;
}

.io-config {
  display: flex;
  flex-direction: column;
  gap: 0.8vh;
}

.io-item {
  display: flex;
  justify-content: space-between;
  font-size: 0.9vw;
}

.io-label {
  opacity: 0.8;
}

.io-value {
  font-weight: 600;
  color: #4CAF50;
}

.no-selection {
  text-align: center;
  padding: 3vh 0;
  opacity: 0.7;
}

.no-selection-icon {
  font-size: 3vw;
  margin-bottom: 1vh;
}

.flow-info {
  background: rgba(255,255,255,0.05);
  border-radius: 8px;
  padding: 1.5vh 1vw;
}

.flow-info h4 {
  margin: 0 0 1vh 0;
  font-size: 1.2vw;
  color: #4CAF50;
  border-bottom: 1px solid rgba(255,255,255,0.2);
  padding-bottom: 0.5vh;
}

.info-item {
  margin-bottom: 1vh;
  display: flex;
  flex-direction: column;
  gap: 0.5vh;
}

.info-label {
  font-size: 1vw;
  opacity: 0.8;
}

.info-input, .info-select, .info-textarea {
  background: rgba(255,255,255,0.1);
  border: 1px solid rgba(255,255,255,0.3);
  border-radius: 5px;
  color: #fff;
  padding: 0.6vh 0.8vw;
  font-size: 0.9vw;
  outline: none;
}

.info-textarea {
  resize: vertical;
  min-height: 60px;
}

.status-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.8vh 2vw;
  background: rgba(0,0,0,0.2);
  border-top: 1px solid rgba(255,255,255,0.2);
  font-size: 0.9vw;
}

.status-left, .status-right {
  display: flex;
  gap: 2vw;
}

.status-item {
  display: flex;
  align-items: center;
  gap: 0.5vw;
  opacity: 0.8;
}

.status-icon {
  font-size: 1vw;
}

/* 模态框样式 */
.modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0,0,0,0.7);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1000;
}

.modal-content {
  background: linear-gradient(135deg, #2a5298, #1e3c72);
  border-radius: 15px;
  width: 80vw;
  max-width: 1000px;
  max-height: 80vh;
  overflow-y: auto;
  border: 1px solid rgba(255,255,255,0.2);
  box-shadow: 0 20px 60px rgba(0,0,0,0.3);
}

.modal-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 2vh 2vw;
  border-bottom: 1px solid rgba(255,255,255,0.2);
}

.modal-header h3 {
  margin: 0;
  font-size: 1.8vw;
}

.close-btn {
  background: none;
  border: none;
  color: #fff;
  font-size: 2vw;
  cursor: pointer;
  padding: 0.5vh 1vw;
  border-radius: 5px;
  transition: background 0.3s ease;
}

.close-btn:hover {
  background: rgba(255,255,255,0.1);
}

.modal-body {
  padding: 2vh 2vw;
}

.template-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 2vw;
}

.template-card {
  background: rgba(255,255,255,0.1);
  border-radius: 10px;
  padding: 2vh 1.5vw;
  cursor: pointer;
  transition: all 0.3s ease;
  border: 1px solid rgba(255,255,255,0.2);
}

.template-card:hover {
  background: rgba(255,255,255,0.2);
  transform: translateY(-3px);
  box-shadow: 0 10px 30px rgba(0,0,0,0.2);
}

.template-icon {
  font-size: 3vw;
  text-align: center;
  margin-bottom: 1vh;
}

.template-name {
  font-size: 1.4vw;
  margin: 0 0 0.5vh 0;
  text-align: center;
}

.template-description {
  font-size: 1vw;
  opacity: 0.8;
  text-align: center;
  margin: 0 0 1vh 0;
  line-height: 1.4;
}

.template-meta {
  display: flex;
  justify-content: space-between;
  font-size: 0.9vw;
  opacity: 0.7;
}

.template-type {
  background: rgba(76, 175, 80, 0.3);
  padding: 0.2vh 0.8vw;
  border-radius: 10px;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .main-editor {
    flex-direction: column;
    height: auto;
  }
  
  .node-palette {
    width: 100%;
    height: 30vh;
  }
  
  .properties-panel {
    width: 100%;
    height: 30vh;
  }
  
  .page-title {
    font-size: 5vw;
  }
  
  .page-subtitle {
    font-size: 2.5vw;
  }
  
  .header-btn {
    font-size: 2vw;
  }
  
  .toolbar {
    flex-direction: column;
    align-items: flex-start;
  }
  
  .template-grid {
    grid-template-columns: 1fr;
  }
  
  .modal-content {
    width: 95vw;
    margin: 1vh;
  }
}

@keyframes pulse {
  0%, 100% {
    opacity: 1;
  }
  50% {
    opacity: 0.5;
  }
}
</style>
